using System;
using System.Collections.Generic;
using ExampleImplementation;
using LoRel;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace CoreTest {
    [TestClass]
    public class SchemaBaseData {

        protected Expression m_PosTrader;
        protected Expression m_PosQty;
        protected Expression m_PosSymbol;

        protected Expression m_MDSymbol;
        protected Expression m_MDPrice;

        private Schema m_Schema = null;

        protected Schema GetSchema() { return m_Schema; }

        #region INIT and CLEANUP

        [TestInitialize]
        public void Initialize()
        {
            m_PosTrader = CORE.Exp.Register("Pos.Trader", PosTrader);
            m_PosQty = CORE.Exp.Register("Pos.Qty", PosQty);
            m_PosSymbol = CORE.Exp.Register("Pos.Symbol", PosSymbol);

            m_MDPrice = CORE.Exp.Register("MD.Price", MDPrice);
            m_MDSymbol = CORE.Exp.Register("MD.Symbol", MDSymbol);

            Schema schema = new Schema(
                new[] { m_PosSymbol, m_PosTrader, m_PosQty },
                new[] { m_PosSymbol, m_PosTrader });

            m_Schema = schema;

            CreatePairs();
        }

        [TestCleanup]
        public void Cleanup()
        {
            Assert.IsTrue(CORE.Exp.DeRegister("Pos.Trader", PosTrader), "Deregister fail");
            m_PosTrader = null;

            Assert.IsTrue(CORE.Exp.DeRegister("Pos.Qty", PosQty));
            m_PosQty = null;

            Assert.IsTrue(CORE.Exp.DeRegister("Pos.Symbol", PosSymbol));
            m_PosSymbol = null;

            Assert.IsTrue(CORE.Exp.DeRegister("MD.Symbol", MDSymbol));
            m_MDSymbol = null;

            Assert.IsTrue(CORE.Exp.DeRegister("MD.Price", MDPrice));
            m_MDPrice = null;
        }

        private IComparable MDSymbol( object input ) {
            MD md = (MD)input;
            return md.Symbol;    
        }

        private IComparable MDPrice( object input ) {
            MD md = (MD)input;
            return md.Price;
        }

        private String PosSymbol(object input)
        {
            Pos pos = (Pos)input;
            return pos.Symbol;
        }

        private String PosTrader(object input)
        {
            Pos pos = (Pos)input;
            return pos.Trader;
        }

        private IComparable PosQty(object input)
        {
            Pos pos = (Pos)input;
            return pos.Qty;
        }

        #endregion

        protected List<KeyPairs> GetData() { return m_Pairs; }

        private List< KeyPairs > m_Pairs = null;

        private void CreatePairs() {

            Schema schema = m_Schema;
            List<KeyPairs> list = new List< KeyPairs >();

            Key lhs = new Key(schema, new[] { "IBM", "Jim", (IComparable)100, });
            Key rhs = new Key(schema, new[] { "IBM", "Jim", (IComparable)100, });
            Pos lhs_pos = new Pos("IBM", "Jim", 100); 
            Pos rhs_pos = new Pos("IBM", "Jim", 100);

            list.Add(  new KeyPairs( lhs, rhs, lhs_pos, rhs_pos, 0, true, "Simple Equality" ) );

            lhs = new Key(schema, new[] { "IBM", "Jim", (IComparable)100, });
            rhs = new Key(schema, new[] { "IBM", "Jim", (IComparable)101, });

            lhs_pos = new Pos("IBM", "Jim", 100);
            rhs_pos = new Pos("IBM", "Jim", 101);

            list.Add(new KeyPairs(lhs, rhs, lhs_pos, rhs_pos, -1, false, "Simple InEquality"));

            lhs = new Key(schema, new[] { "IBM", (IComparable)null, (IComparable)100, });
            rhs = new Key(schema, new[] { "IBM", (IComparable)null, (IComparable)100, });

            lhs_pos = new Pos("IBM", null, 100);
            rhs_pos = new Pos("IBM", null, 100);

            list.Add(new KeyPairs(lhs, rhs, lhs_pos, rhs_pos, 0, true, "Equality Second Field Null"));

            lhs = new Key(schema, new[] { "IBM", (IComparable)null, (IComparable)100, });
            rhs = new Key(schema, new[] { "IBM", (IComparable)null, (IComparable)101, });

            lhs_pos = new Pos("IBM", null, 100);
            rhs_pos = new Pos("IBM", null, 101);

            list.Add(new KeyPairs(lhs, rhs, lhs_pos, rhs_pos, -1, false, "Second Field Null, InEquality on Third"));

            lhs = new Key(schema, new[] { "IBM", (IComparable)null, (IComparable)100, });
            rhs = new Key(schema, new[] { "IBM", (IComparable)"Sam", (IComparable)100, });

            lhs_pos = new Pos("IBM", null, 100);
            rhs_pos = new Pos("IBM", "Sam", 100);

            list.Add(new KeyPairs(lhs, rhs, lhs_pos, rhs_pos, -1, false, "InEquality. Second in LHS Null."));

            lhs = new Key(schema, new[] { "IBM", (IComparable)"Sam", (IComparable)100, });
            rhs = new Key(schema, new[] { "IBM", (IComparable)null, (IComparable)100, });

            lhs_pos = new Pos("IBM", "Sam", 100);
            rhs_pos = new Pos("IBM", null, 100);

            list.Add(new KeyPairs(lhs, rhs, lhs_pos, rhs_pos, 1, false, "InEquality, Second in RHS Null."));

            m_Pairs = list;
        }

        public class KeyPairs {

            public KeyPairs(Key lhs, Key rhs, Pos lhs_pos, Pos rhs_pos, int correct_compare_result, bool correct_equality_result, string message)
            {
                LHS = lhs;
                RHS = rhs;
                LHS_Pos = lhs_pos;
                RHS_Pos = rhs_pos;
                CorrectCompareResult = correct_compare_result;
                CorrectEqualityResult = correct_equality_result;

                Description = message;
            }

            public String Description { get; private set; }
            public Key LHS { get; private set; }
            public Key RHS { get; private set; }
            public Pos LHS_Pos { get; private set; }
            public Pos RHS_Pos { get; private set; }
            public int CorrectCompareResult { get; private set; }
            public bool CorrectEqualityResult { get; private set; }
        }

    }
}